import struct
from typing import Union, Dict, Any

class NewBinaryProtocol:
    FORMAT_HEADER = '>BBH'  # Big-endian byte order, unsigned char, unsigned char, unsigned short
    HEADER_SIZE = struct.calcsize(FORMAT_HEADER)

    def __init__(self, type: int, reserved: int, payload: Union[bytes, str]):
        self.type = type
        self.reserved = reserved
        if isinstance(payload, str):
            self.payload = payload.encode('utf-8')
        else:
            self.payload = payload
        self.payload_size = len(self.payload)

    def serialize(self) -> bytes:
        header = struct.pack(self.FORMAT_HEADER, self.type, self.reserved, self.payload_size)
        return header + self.payload

    @classmethod
    def deserialize(cls, data: bytes) -> 'NewBinaryProtocol':
        header = data[:cls.HEADER_SIZE]
        payload = data[cls.HEADER_SIZE:]
        type, reserved, payload_size = struct.unpack(cls.FORMAT_HEADER, header)
        if len(payload) != payload_size:
            raise ValueError("Payload size does not match the expected length")
        return cls(type, reserved, payload)

    def to_dict(self) -> Dict[str, Any]:
        return {
            'type': self.type,
            'reserved': self.reserved,
            'payload_size': self.payload_size,
            'payload': self.payload.decode('utf-8') if isinstance(self.payload, bytes) else self.payload
        }

    @classmethod
    def from_dict(cls, d: Dict[str, Any]) -> 'NewBinaryProtocol':
        return cls(d['type'], d['reserved'], d['payload'])

class BinaryProtocol:
    def __init__(self, data):
        self.data = data
        self.type = None
        self.reserved = None
        self.payload_size = None
        self.payload = None
        self.unpack()

    def unpack(self):
        header = self.data[:4]
        self.type, self.reserved = struct.unpack('=BB', header[:2])
        self.payload_size, = struct.unpack('>H', header[2:])
        self.payload = self.data[4:4 + self.payload_size]

    def to_dict(self):
        return {
            'type': self.type,
            'reserved': self.reserved,
            'payload_size': self.payload_size,
            'payload': self.payload
        }

    def __str__(self):
        return f"Type: {self.type}, Reserved: {self.reserved}, Payload Size: {self.payload_size}, Payload: {self.payload}"